import '../prompt/prompt.css'
import Prompt from '../prompt/prompt.js'
import BasePlot from './basePlot';
import util from '../util';

/**
 * 扇形标绘类（支持标绘后编辑位置和大小）
 * @class
 * @augments BasePlot
 * @alias BasePlot.CreateSector
 */
class CreateSector extends BasePlot {
  constructor(viewer, style) {
    super(viewer, style);
    this.type = "sector";
    this.viewer = viewer;
    this.style = style;

    /**
     * @property {Cesium.Entity} centerPoint 扇形中心点实体点（编辑控制点）
     */
    this.centerPoint = null;

    /**
     * @property {Cesium.Entity} edgePoint 扇形边缘点实体点（控制半径）
     */
    this.edgePoint = null;

    /**
     * @property {Cesium.Entity} anglePoint 扇形角度控制实体点（控制角度范围）
     */
    this.anglePoint = null;

    /**
     * @property {Cesium.Cartesian3} center 扇形中心点坐标
     */
    this.center = null;

    /**
     * @property {Cesium.Cartesian3} edge 扇形边缘点坐标
     */
    this.edge = null;

    /**
     * @property {Cesium.Cartesian3} angle 扇形角度控制坐标
     */
    this.angle = null;

    /**
     * @property {Number} radius 扇形半径
     */
    this.radius = 0;

    /**
     * @property {Number} startAngle 扇形起始角度（弧度）
     */
    this.startAngle = 0;

    /**
     * @property {Number} endAngle 扇形结束角度（弧度）
     */
    this.endAngle = 0;

    this.modifyPoint = null; // 当前拖拽的控制点
    this.pointArr = []; // 控制点集合
    this.modifyHandler = null; // 编辑事件处理器
  }

  /**
   * 开始标绘扇形
   * @param {Function} callback 标绘完成回调函数
   */
  start(callback) {
    if (!this.prompt && this.promptStyle.show) {
      this.prompt = new Prompt(this.viewer, this.promptStyle);
    }
    this.state = "startCreate";
    const that = this;

    // 初始化绘制事件处理器
    if (!this.handler) {
      this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    }

    // 左键点击事件 - 确定标绘点
    this.handler.setInputAction(function (evt) {
      const cartesian = that.getCatesian3FromPX(evt.position, that.viewer, []);
      if (!cartesian) return;

      if (!that.centerPoint) {
        // 第一点：中心点
        that.center = cartesian;
        that.centerPoint = that.createPoint(cartesian);
        that.centerPoint.typeAttr = "center";
        that.edgePoint = that.createPoint(cartesian.clone());
        that.edge = cartesian.clone();
        that.edgePoint.typeAttr = "edge";
        that.anglePoint = that.createPoint(cartesian.clone());
        that.angle = cartesian.clone();
        that.anglePoint.typeAttr = "angle";
        that.entity = that.createSector();
      } else if (!that.edgePoint.position._value.equals(that.center)) {
        // 第二点：边缘点（确定半径）
        that.edge = cartesian;
        that.edgePoint.position.setValue(cartesian);
        that.radius = Cesium.Cartesian3.distance(that.center, that.edge);
        
        // 计算起始角度
        const north = Cesium.Cartesian3.normalize(
          Cesium.Cartesian3.subtract(that.edge, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        const east = new Cesium.Cartesian3(-north.y, north.x, 0);
        const transform = new Cesium.Matrix3(
          east.x, north.x, 0,
          east.y, north.y, 0,
          east.z, north.z, 1
        );
        const localEdge = Cesium.Matrix3.multiplyByVector(
          transform,
          Cesium.Cartesian3.subtract(that.edge, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        that.startAngle = Math.atan2(localEdge.y, localEdge.x);
        that.entity = that.createSector();
      } else {
        // 第三点：角度点（确定角度范围）
        if (!that.entity) return;
        that.angle = cartesian;
        that.anglePoint.position.setValue(cartesian);
        
        // 计算结束角度
        const north = Cesium.Cartesian3.normalize(
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        const east = new Cesium.Cartesian3(-north.y, north.x, 0);
        const transform = new Cesium.Matrix3(
          east.x, north.x, 0,
          east.y, north.y, 0,
          east.z, north.z, 1
        );
        const localAngle = Cesium.Matrix3.multiplyByVector(
          transform,
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        that.endAngle = Math.atan2(localAngle.y, localAngle.x);
        
        // 标绘完成，隐藏控制点
        that.endCreate();
        if (callback) callback(that.entity);
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    // 鼠标移动事件 - 动态绘制
    this.handler.setInputAction(function (evt) {
      if (!that.centerPoint) {
        that.prompt.update(evt.endPosition, "单击确定扇形中心点");
        return;
      } else if (that.edgePoint.position._value.equals(that.center)) {
        that.prompt.update(evt.endPosition, "单击确定扇形边缘点（控制半径）");
        const cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, []);
        if (!cartesian) return;
        that.edgePoint.position.setValue(cartesian);
        that.edge = cartesian.clone();
        that.radius = Cesium.Cartesian3.distance(that.center, that.edge);
        that.entity = that.createSector();
      } else {
        that.prompt.update(evt.endPosition, "单击确定扇形角度范围");
        const cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, []);
        if (!cartesian) return;
        that.anglePoint.position.setValue(cartesian);
        that.angle = cartesian.clone();
        
        // 实时更新结束角度
        const north = Cesium.Cartesian3.normalize(
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        const east = new Cesium.Cartesian3(-north.y, north.x, 0);
        const transform = new Cesium.Matrix3(
          east.x, north.x, 0,
          east.y, north.y, 0,
          east.z, north.z, 1
        );
        const localAngle = Cesium.Matrix3.multiplyByVector(
          transform,
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        that.endAngle = Math.atan2(localAngle.y, localAngle.x);
        that.entity = that.createSector();
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }

  /**
   * 结束标绘
   */
  endCreate() {
    const that = this;
    if (that.handler) {
      that.handler.destroy();
      that.handler = null;
    }
    // 隐藏控制点（编辑时再显示）
    if (that.centerPoint) that.centerPoint.show = false;
    if (that.edgePoint) that.edgePoint.show = false;
    if (that.anglePoint) that.anglePoint.show = false;
    if (that.prompt) {
      that.prompt.destroy();
      that.prompt = null;
    }
    that.state = "endCreate";
  }

  /**
   * 结束当前操作（绘制或编辑）
   */
  done() {
    if (this.state === "startCreate" || this.state === "creating") {
      this.destroy();
    } else if (this.state === "startEdit" || this.state === "editing") {
      this.endEdit();
    }
  }

  /**
   * 开始编辑扇形（支持调整位置、半径和角度）
   * @param {Function} callback 编辑回调函数
   */
  startEdit(callback) {
    if (this.state === "startEdit" || this.state === "editing" || !this.entity) return;
    this.state = "startEdit";

    // 初始化编辑事件处理器
    if (!this.modifyHandler) {
      this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    }

    const that = this;
    // 显示控制点
    if (that.centerPoint) that.centerPoint.show = true;
    if (that.edgePoint) that.edgePoint.show = true;
    if (that.anglePoint) that.anglePoint.show = true;

    // 鼠标按下 - 拾取控制点
    this.modifyHandler.setInputAction(function (evt) {
      if (!that.entity) return;
      const pick = that.viewer.scene.pick(evt.position);
      if (Cesium.defined(pick) && pick.id) {
        if (!pick.id.objId) {
          that.modifyPoint = pick.id; // 记录当前拖拽的控制点
          that.forbidDrawWorld(true); // 禁止地图操作
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

    // 鼠标移动 - 更新控制点位置（实时调整扇形）
    this.modifyHandler.setInputAction(function (evt) {
      if (!that.modifyPoint) return;
      const cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity, that.modifyPoint]);
      if (!cartesian) return;

      that.state = "editing";
      if (that.modifyPoint.typeAttr === "center") {
        // 移动中心点（整体平移）
        const offset = Cesium.Cartesian3.subtract(cartesian, that.center, new Cesium.Cartesian3());
        that.center = cartesian;
        that.centerPoint.position.setValue(that.center);

        // 同步偏移边缘点和角度点
        that.edge = Cesium.Cartesian3.add(that.edge, offset, new Cesium.Cartesian3());
        that.edgePoint.position.setValue(that.edge);
        that.angle = Cesium.Cartesian3.add(that.angle, offset, new Cesium.Cartesian3());
        that.anglePoint.position.setValue(that.angle);

        // 重新计算半径和角度（确保数据一致性）
        that.radius = Cesium.Cartesian3.distance(that.center, that.edge);
      } else if (that.modifyPoint.typeAttr === "edge") {
        // 移动边缘点（调整半径和起始角度）
        that.edge = cartesian;
        that.edgePoint.position.setValue(that.edge);
        that.radius = Cesium.Cartesian3.distance(that.center, that.edge);

        // 重新计算起始角度
        const north = Cesium.Cartesian3.normalize(
          Cesium.Cartesian3.subtract(that.edge, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        const east = new Cesium.Cartesian3(-north.y, north.x, 0);
        const transform = new Cesium.Matrix3(
          east.x, north.x, 0,
          east.y, north.y, 0,
          east.z, north.z, 1
        );
        const localEdge = Cesium.Matrix3.multiplyByVector(
          transform,
          Cesium.Cartesian3.subtract(that.edge, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        that.startAngle = Math.atan2(localEdge.y, localEdge.x);
      } else if (that.modifyPoint.typeAttr === "angle") {
        // 移动角度点（调整结束角度）
        that.angle = cartesian;
        that.anglePoint.position.setValue(that.angle);

        // 重新计算结束角度
        const north = Cesium.Cartesian3.normalize(
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        const east = new Cesium.Cartesian3(-north.y, north.x, 0);
        const transform = new Cesium.Matrix3(
          east.x, north.x, 0,
          east.y, north.y, 0,
          east.z, north.z, 1
        );
        const localAngle = Cesium.Matrix3.multiplyByVector(
          transform,
          Cesium.Cartesian3.subtract(that.angle, that.center, new Cesium.Cartesian3()),
          new Cesium.Cartesian3()
        );
        that.endAngle = Math.atan2(localAngle.y, localAngle.x);
      }

      // 重新绘制扇形
      that.entity = that.createSector();
      if (callback) callback(that.entity);
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // 鼠标释放 - 结束当前编辑操作
    this.modifyHandler.setInputAction(function () {
      if (that.modifyPoint) {
        that.modifyPoint = null;
        that.forbidDrawWorld(false); // 恢复地图操作
      }
    }, Cesium.ScreenSpaceEventType.LEFT_UP);
  }

  /**
   * 结束编辑
   * @param {Function} callback 结束回调函数
   */
  endEdit(callback) {
    // 隐藏控制点
    if (this.centerPoint) this.centerPoint.show = false;
    if (this.edgePoint) this.edgePoint.show = false;
    if (this.anglePoint) this.anglePoint.show = false;

    // 销毁编辑事件处理器
    if (this.modifyHandler) {
      this.modifyHandler.destroy();
      this.modifyHandler = null;
    }

    this.forbidDrawWorld(false);
    this.state = "endEdit";
    if (callback) callback(this.entity);
  }

  /**
   * 创建扇形实体
   * @returns {Cesium.Entity} 扇形实体
   */
  createSector() {
    // 移除旧实体
    if (this.entity) {
      this.viewer.entities.remove(this.entity);
    }

    const that = this;
    // 计算扇形顶点（使用CallbackProperty实现动态更新）
    const positionsCallback = new Cesium.CallbackProperty(() => {
      const positions = [that.center]; // 起点为中心点

      // 角度步长（控制扇形平滑度）
      const step = 0.01;
      let currentAngle = that.startAngle;
      const isClockwise = that.endAngle < that.startAngle;

      // 生成扇形边缘点
      while (isClockwise ? currentAngle >= that.endAngle : currentAngle <= that.endAngle) {
        const x = that.center.x + that.radius * Math.cos(currentAngle);
        const y = that.center.y + that.radius * Math.sin(currentAngle);
        positions.push(new Cesium.Cartesian3(x, y, that.center.z));
        currentAngle += isClockwise ? -step : step;
      }

      positions.push(that.center); // 闭合扇形
      return positions;
    }, false);

    // 创建扇形面实体
    return this.viewer.entities.add({
      polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
          return new Cesium.PolygonHierarchy(positionsCallback.getValue());
        }, false),
        heightReference: this.style.heightReference || Cesium.HeightReference.NONE,
        fill: this.style.fill !== undefined ? this.style.fill : true,
        material: this.style.color
          ? Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 0.5)
          : Cesium.Color.RED.withAlpha(0.5),
        outline: this.style.outline !== undefined ? this.style.outline : true,
        outlineColor: this.style.outlineColor
          ? Cesium.Color.fromCssColorString(this.style.outlineColor)
          : Cesium.Color.BLACK,
        outlineWidth: this.style.outlineWidth || 1,
        disableDepthTestDistance: Number.POSITIVE_INFINITY
      }
    });
  }

  /**
   * 获取扇形坐标信息
   * @param {Boolean} isWgs84 是否返回经纬度坐标
   * @returns {Array} 坐标数组
   */
  getPositions(isWgs84) {
    const positions = [this.center, this.edge, this.angle];
    return isWgs84
      ? util.cartesiansToLnglats(positions, this.viewer)
      : positions;
  }

  /**
   * 获取当前样式配置
   * @returns {Object} 样式配置
   */
  getStyle() {
    if (!this.entity) return {};
    const polygon = this.entity.polygon;
    const color = polygon.material.color.getValue();
    const outlineColor = polygon.outlineColor.getValue();

    return {
      color: Cesium.Color.fromRgba(color).toCssHexString(),
      colorAlpha: color.alpha,
      outline: polygon.outline.getValue(),
      outlineColor: Cesium.Color.fromRgba(outlineColor).toCssHexString(),
      outlineWidth: polygon.outlineWidth._value,
      heightReference: polygon.heightReference.getValue()
    };
  }

  /**
   * 设置扇形样式
   * @param {Object} style 样式配置
   */
  setStyle(style) {
    if (!style || !this.entity) return;
    const polygon = this.entity.polygon;

    if (style.color) {
      const color = Cesium.Color.fromCssColorString(style.color)
        .withAlpha(style.colorAlpha !== undefined ? style.colorAlpha : 0.5);
      polygon.material = color;
    }

    if (style.outline !== undefined) polygon.outline = style.outline;
    if (style.outlineColor) {
      polygon.outlineColor = Cesium.Color.fromCssColorString(style.outlineColor);
    }
    if (style.outlineWidth) polygon.outlineWidth = style.outlineWidth;
    if (style.heightReference !== undefined) {
      polygon.heightReference = style.heightReference;
    }

    this.style = { ...this.style, ...style };
  }

  /**
   * 销毁扇形标绘
   */
  destroy() {
    if (this.entity) {
      this.viewer.entities.remove(this.entity);
    }
    if (this.centerPoint) {
      this.viewer.entities.remove(this.centerPoint);
    }
    if (this.edgePoint) {
      this.viewer.entities.remove(this.edgePoint);
    }
    if (this.anglePoint) {
      this.viewer.entities.remove(this.anglePoint);
    }
    if (this.handler) {
      this.handler.destroy();
      this.handler = null;
    }
    if (this.modifyHandler) {
      this.modifyHandler.destroy();
      this.modifyHandler = null;
    }
    this.state = null;
  }
}

export default CreateSector;